#include <iostream>
#include <vector>
#include "Util/Util.h"
#include "CWJBplusSE.h"
#include <map>

#include "LibrarySys/LibrarySys.h"


using namespace std;
using namespace CWJ::BPlusSE;
using namespace CWJ::LibSys;

template<typename BplusTree,typename Map>
void testMap( BplusTree &tree, Map &mm){
    Map tmp;
    for(auto t : tree){
        tmp[t.key] = t.val;
    }
    assert(tmp == mm);
    cout<<"testMap accept"<<endl;
}


template<typename BplusTree,typename Map>
void testMap2( BplusTree &tree, Map &mm){
    int count = 0;
    for(auto a : tree){
        count++;
        if(a.val!=mm[a.key]) {
            cout <<"count:"<<count<< " key: " << a.key << " " << a.val << " " << mm[a.key] << endl;
            exit(-1);
            assert(false);
        }
    }

    assert(count == mm.size());

    cout<<"testMap2 accept"<<endl;

}

template<typename BplusTree>
void test(BplusTree &tree,const vector<pair<int,int>>&list){
    vector<BPlusTree<int,int>::Item>nums(tree.begin(),tree.end());
    cout<<list.size()<<" "<<nums.size()<<endl;
    assert(list.size() == nums.size());
    for(int i=0;i<list.size();i++){
        if(!(list[i].first == nums[i].key && list[i].second == nums[i].val)){
            cerr<<list[i].first<<" "<< list[i].second<<" "<<nums[i].key<<" "<<nums[i].val<<endl;
        }
        assert(list[i].first == nums[i].key && list[i].second == nums[i].val);
    }
    cout<<"test accept"<<endl;
}

int main(){

    BPlusTree<int,int>tree("tree.db",true);
    BPlusTree<int,int>treeTest("treeTest.db",true);
    vector<pair<int,int>>list;
    map<int,int>tree_map;
    for(int i =0;i<100000;i++) {
        int key = i,val = i+(rand()%10);
        list.push_back({key,val});
        tree_map[key] = val;
    }

    cout<<" ------------------- 功能性测试：10W int insert and delete  -------------------"<<endl;

    cout<<calcTime([&treeTest,&list](){treeTest.insertOrderBatch(list);})<<" ms "<<endl;

    test(treeTest,list);


    for(int i=0;i<300;i++){
        int key = rand()%1000;
        treeTest.remove(key);
        tree_map.erase(key);
    }

    testMap(treeTest,tree_map);


    cout<<"----------------------压测 : ---------------------------------------"<<endl;
    cout<< "-------------------- insert 10W  CharIndex<20>,CharINdex<30>--------------"<<endl;
    cout<<"key size:"<<sizeof (CharIndex<20>) <<"  "<<"val size:"<<sizeof(CharIndex<30>) << endl;
    BPlusTree <CharIndex<20>,CharIndex<30>> test_bplus_book("test_Library_book.db",true);
    vector<pair<CharIndex<20>,CharIndex<30>>> test_list;
    map<CharIndex<20>,CharIndex<30>> test_map;
    for(int i =0;i<100000;i++) {
        auto  key = CharIndex<20>(to_string(i).c_str());
        auto val = CharIndex<30>(to_string(rand()).c_str());
        test_list.push_back({key,val});
        test_map[key] = val;
    }
    cout<<calcTime([&test_bplus_book,&test_list](){test_bplus_book.insertUnOrderBatch(test_list);})<<" ms "<<endl;


    testMap2(test_bplus_book,test_map);


    cout<<"----------------------压测 : ---------------------------------------"<<endl;
    cout<< "-------------------- insert 1W  uint64 CHarIndex<1024> --------------"<<endl;
    cout<<"key size:"<<sizeof (uint64_t) <<"  "<<"val size:"<<sizeof(CharIndex<1024>) << endl;
    BPlusTree <uint64_t ,CharIndex<1024>> test_uint64_char1024_tree("test_Library_book.db",true);
    vector<pair<uint64_t ,CharIndex<1024>>> test_uint64_list;
    map<uint64_t ,CharIndex<1024>> test_uint64_map;
    for(int i =0;i<10000;i++) {
        auto val = CharIndex<1024>(to_string(rand()).c_str());
        test_uint64_list.push_back({i,val});
        test_uint64_map[i] = val;
    }
    cout<<calcTime([&test_uint64_char1024_tree,&test_uint64_list](){test_uint64_char1024_tree.insertOrderBatch(test_uint64_list);})<<" ms "<<endl;


    testMap2(test_uint64_char1024_tree,test_uint64_map);



    return 0;
}
